[PowerShell] Script to restart a service and its dependents (and their dependents)

I am trying to write a PowerShell script that will restart the SNMP Service on a server.  The server in question is an HP server that has the various HP Insight agents installed, and some of these depend on the SNMP Service.  One of these services also depends on one of the other HP Insight services (that in turn depends on SNMP Service).


I can easily write a script that stops and starts the specific services in order, but I don't want to do that.  I like to create scripts that are as flexible as possible.  In this case, I'd like to write a script that takes a service name as input and can restart that service, including any dependents (and dependents of those dependents, and dependents of those dependents).  They way to do this seems to be recursion, but I simply cannot get it to work correctly.  Here is what I have so far (just trying to get the services to stop in the correct order):

$MainServiceName = "SNMP"
$ServiceInput = ""
$CurrentService = ""
$Service = ""

function Custom-Stop-Service ($ServiceInput)
{
	Write-Host "Name of `$ServiceInput: $($ServiceInput.Name)"
	Write-Host "Number of dependents: $($ServiceInput.DependentServices.Count)"
	If ($ServiceInput.DependentServices.Count -gt 0)
	{
		ForEach ($Service in $ServiceInput.DependentServices)
		{
			Write-Host "Dependent of $($ServiceInput.Name): $($Service.Name)"
			If ($Service.Status -eq "Running")
			{
				Write-Host "$($Service.Name) is running."
				$CurrentService = Get-Service -Name $Service.Name
				
				Custom-Stop-Service $CurrentService
				Write-Host "Stopping service $($CurrentService.Name)"
				Stop-Service -Name $CurrentService.Name -Force
			}
			Else
			{
				Write-Host "$($Service.Name) is stopped."
			}
			
		}
	}
	Else
	{
		Write-Host "Stopping service $($ServiceInput.Name)"
		Stop-Service -Name $ServiceInput.Name
	}
}

$MainService = Get-Service -Name $MainServiceName

If ($MainService.Status -eq "Stopped")
{
	Write-Host "Service $($MainService.Name) is already stopped."
}
Else
{
	Custom-Stop-Service $MainService
}


However, it doesn't work like I expect.  Firstly, it never attempts to stop the SNMP service itself.  Secondly while it does seem to stop all the dependents of SNMP correctly, it tries to stop CqMgHost twice.  Here is the output:

PS C:\Scripts> .\restart_service.ps1
Name of $ServiceInput: SNMP
Number of dependents: 4
Dependent of SNMP: CqMgHost
CqMgHost is running.
Name of $ServiceInput: CqMgHost
Number of dependents: 0
Stopping service CqMgHost
WARNING: Waiting for service 'HP Insight Foundation Agents (CqMgHost)' to finish stopping...
WARNING: Waiting for service 'HP Insight Foundation Agents (CqMgHost)' to finish stopping...
WARNING: Waiting for service 'HP Insight Foundation Agents (CqMgHost)' to finish stopping...
WARNING: Waiting for service 'HP Insight Foundation Agents (CqMgHost)' to finish stopping...
Stopping service CqMgHost
Dependent of SNMP: CqMgStor
CqMgStor is running.
Name of $ServiceInput: CqMgStor
Number of dependents: 1
Dependent of CqMgStor: CqMgHost
CqMgHost is stopped.
Stopping service CqMgStor
Dependent of SNMP: CqMgServ
CqMgServ is running.
Name of $ServiceInput: CqMgServ
Number of dependents: 1
Dependent of CqMgServ: CqMgHost
CqMgHost is stopped.
Stopping service CqMgServ
WARNING: Waiting for service 'HP Insight Server Agents (CqMgServ)' to finish stopping...
WARNING: Waiting for service 'HP Insight Server Agents (CqMgServ)' to finish stopping...
Dependent of SNMP: CpqNicMgmt
CpqNicMgmt is running.
Name of $ServiceInput: CpqNicMgmt
Number of dependents: 1
Dependent of CpqNicMgmt: CqMgHost
CqMgHost is stopped.
Stopping service CpqNicMgmt

Can someone suggest a different script or changes to my script so that it will do what I want?  I know that "Stop-Service -Name SNMP -Force" will work but there are two problems with this: 1) it doesn't record the stop events for the dependents in the Event Viewer and 2) it doesn't work in reverse ("Start-Service -Name SNMP -Force" nor "Restart-Service -Name SNMP -Force" restart the main service and the other services that depend on SNMP that were stopped).

I'm a little surprised that Restart-Service doesn't behave like the restart function in the Services MMC does, where it easily and reliably handles the stops and starts of not only the service itself, but dependent services and also properly does event logging.

 

 

November 29th, 2011 4:03pm

(Get-Service SomeService).DependentServices | Stop-Service
Free Windows Admin Tool Kit Click here and download it now
November 29th, 2011 5:46pm

Unfortunately, that does not work:

 

PS C:\Scripts> (Get-Service -Name "SNMP").DependentServices | Stop-Service
WARNING: Waiting for service 'HP Insight Foundation Agents (CqMgHost)' to finish stopping...
WARNING: Waiting for service 'HP Insight Foundation Agents (CqMgHost)' to finish stopping...
WARNING: Waiting for service 'HP Insight Foundation Agents (CqMgHost)' to finish stopping...
WARNING: Waiting for service 'HP Insight Foundation Agents (CqMgHost)' to finish stopping...
Stop-Service : Cannot stop service 'HP Insight Storage Agents (CqMgStor)' because it has dependent services. It can onl
y be stopped if the Force flag is set.
At line:1 char:60
+ (Get-Service -Name "SNMP").DependentServices | Stop-Service <<<<
    + CategoryInfo          : InvalidOperation: (System.ServiceProcess.ServiceController:ServiceController) [Stop-Serv
   ice], ServiceCommandException
    + FullyQualifiedErrorId : ServiceHasDependentServices,Microsoft.PowerShell.Commands.StopServiceCommand

Stop-Service : Cannot stop service 'HP Insight Server Agents (CqMgServ)' because it has dependent services. It can only
 be stopped if the Force flag is set.
At line:1 char:60
+ (Get-Service -Name "SNMP").DependentServices | Stop-Service <<<<
    + CategoryInfo          : InvalidOperation: (System.ServiceProcess.ServiceController:ServiceController) [Stop-Serv
   ice], ServiceCommandException
    + FullyQualifiedErrorId : ServiceHasDependentServices,Microsoft.PowerShell.Commands.StopServiceCommand

Stop-Service : Cannot stop service 'HP Insight NIC Agents (CpqNicMgmt)' because it has dependent services. It can only
be stopped if the Force flag is set.
At line:1 char:60
+ (Get-Service -Name "SNMP").DependentServices | Stop-Service <<<<
    + CategoryInfo          : InvalidOperation: (System.ServiceProcess.ServiceController:ServiceController) [Stop-Serv
   ice], ServiceCommandException
    + FullyQualifiedErrorId : ServiceHasDependentServices,Microsoft.PowerShell.Commands.StopServiceCommand

Adding -Force to the end does stop the services, except it still doesn't stop the SNMP service (the parent service).  Also, it doesn't correctly handle dependents of dependents.

 


November 29th, 2011 6:07pm

TO stop a service and its dependents use the -force parameter.

To restart you must enumerate the dependents and start each one before starting the main service.

Restart-Service <servicename> -force will restart a service and dependents.

 I just ran this on a Proliant DL370 G6 with HP Insight Management and it works correctly

 

Free Windows Admin Tool Kit Click here and download it now
November 29th, 2011 6:12pm

I just tried "Restart-Service -Name SNMP -Force" and it does stop all the dependent HP services and the SNMP service itself, but it only restarts the SNMP service.  HP ProLiant DL380 G5.

I guess I need to know how to do the recursion.  I have no trouble finding the dependents of a main service, but I run into trouble when I try to make the script recursive to handle potentially an infinite number of sub-dependents.

November 29th, 2011 7:14pm

What OS?

I tried on WS2008 R2 and it appears that all dependent services started. 

Are you sure you are up-to-date on the agents and HP services?

 

Free Windows Admin Tool Kit Click here and download it now
November 29th, 2011 8:02pm

This will do the trick:

Restart-Service SNMP -force
Get-Service snmp | Select-Object -expand dependentservices | Start-Service

November 29th, 2011 8:08pm

This is aso a possibility.

$runningServices = Get-Service | Where-Object { $_.Status -eq "running"}
Restart-Service winmgmt -force
$runningServices | Where-Object { ((Get-Service $_.Name).Status) -ne "running" } | Start-Service

Free Windows Admin Tool Kit Click here and download it now
November 29th, 2011 8:41pm

Jure - it's cute but doesn't work.  You must use the dependent services list to start the remaining services.

This looks like it would work but you can get a race condition becuse some services may be being stoped by other processes in a large system.  The dependent services list is targeted very exactly.  A mismatch can force a stopeed service to run that shuold not be running.

 

 

November 29th, 2011 8:47pm

I agree, but your code isn't perfect as well. It is very likely you would be starting services that wasn't running before the restart of service, or am I missing something here?

Regards!

Free Windows Admin Tool Kit Click here and download it now
November 29th, 2011 9:07pm

, or am I missing something here?

You are definitely missing something.  The wholepoint of 'DependantServices' is that these are the services that absolutely MUST be stopped before you can stop the main service.

The 'force' in PosH v2 fails to force the restart as it should. When we use the service manager snapin the dependenat services are automtically restarted. 

I believe this is fixed in V3.

For a couple of years now, most have known about the enumeration of dependant services piped to Start-Service. It is the most realible way to do this in PowerShell.

 

November 29th, 2011 9:21pm

, or am I missing something here?

You are definitely misisngsomething.  YThe wholepoint of 'DependantServices' is that these are the services that absolutely MUST be running before you can start the main service.

The 'force' in PosH v2 fails to force the start as it should. When we use the service manager snapin the dependenat ervices are automtically restarted. 

I believe this is fixed in V3.

For a couple of years now most have known about teh enumeration of dependant services piped to Start-Service. It is the most realible way to do this in PowerShell.

 

Free Windows Admin Tool Kit Click here and download it now
November 30th, 2011 3:16pm

Exactly.  If SNMP is 'forced' to shut down usign '-force' then those service will have to stop.  They depend on SNMP.  When we restart SNMP they do not start unless there is a reference in the master service that will cause it to start them.  In this case they have to be restarted so we enumerate the list and start them.

Just try it.

Stop-Service SNMP -force
Get-Service | select -expand DependentServices | get-Service

You will notice they are all stopped. Now do this:

Get-Service | select -expand DependentServices | get-Service| Start-Service
Get-Service | select -expand DependentServices | get-Service

Notice how they are all now running.

What could be more obvious?

 What else could 'DependentService' possibly mean?

November 30th, 2011 4:31pm

Exactly.  If SNMP is 'forced' to shut down usign '-force' then those service will have to stop.  They depend on SNMP.  When we restart SNMP they do not start unless there is a reference in the master service that will cause it to start them.  In this case they have to be restarted so we enumerate the list and start them.

Just try it.

Stop-Service SNMP -force
Get-Service | select -expand DependentServices | get-Service

You will notice they are all stopped. Now do this:

Get-Service | select -expand DependentServices | get-Service| Start-Service
Get-Service | select -expand DependentServices | get-Service

Notice how they are all now running.

What could be more obvious?

 What else could 'DependentService' possibly mean?

Free Windows Admin Tool Kit Click here and download it now
November 30th, 2011 4:40pm

Sorry - I misunderstood.  YOU wrote something that appeared to say the opposite.

Yes. I should have said the opposite however the code is correct.

I fixed the wording to reflect the correct logic. and also fixed a couple of typos.

You are definitely missing something.  The wholepoint of 'DependantServices' is that these are the services that absolutely MUST be stopped before you can stop the main service.

The 'force' in PosH v2 fails to force the restart as it should. When we use the service manager snapin the dependenat services are automtically restarted. 

Thanks for catching that.

November 30th, 2011 4:44pm

You are right in that something like your code will work for SNMP on a HP server with the management agents installed (I say something like your code because your code is trying to start all services that are listed as dependent services and not all of those should be started necessarily, like Volume Shadow Copy).

That said, it may not correctly work for all parent services due to situations where there might be dependents of dependents.  Sure, if you use your code and start practically every service there is, I think it would work.  But that is not what I am trying to accomplish.  I am trying to:

  1. Take a parent service
  2. Check if it has dependents.
  3. For each dependent, repeat step 2.
  4. Stop the deepest dependent service and work backwards until all dependents are stopped.
  5. Stop the parent service.
  6. Reverse the process (start the services).

Again, something like your script will work for this specific case.  But it will not necessarily work correctly in all scenarios and that is what I am trying to accomplish.  Recursion is the answer here, but I can't figure out the logic just yet.

Free Windows Admin Tool Kit Click here and download it now
November 30th, 2011 5:00pm

You are right in that something like your code will work for SNMP on a HP server with the management agents installed (I say something like your code because your code is trying to start all services that are listed as dependent services and not all of those should be started necessarily, like Volume Shadow Copy).

That said, it may not correctly work for all parent services due to situations where there might be dependents of dependents.  Sure, if you use your code and start practically every service there is, I think it would work.  But that is not what I am trying to accomplish.  I am trying to:

  1. Take a parent service
  2. Check if it has dependents.
  3. For each dependent, repeat step 2.
  4. Stop the deepest dependent service and work backwards until all dependents are stopped.
  5. Stop the parent service.
  6. Reverse the process (start the services).

Again, something like your script will work for this specific case.  But it will not necessarily work correctly in all scenarios and that is what I am trying to accomplish.  Recursion is the answer here, but I can't figure out the logic just yet.


HP agents have no dependencies and VSC is not dependent on HP agaents.

I have no idea what you are trying to say.  The If the services dependents have dependents the jsut keep walking the chain exactly as I have until the end.  I have looked at three servers and have found no dependencies on SNMP below one level.  Certainly VSC should never be dependent.

The other code point I was making is that you can use Get-Service and select dependentservice to walk the chain.  It is not really necessary to use such a complex code bloc.

If the core you have works then use it.  I was only providing a much more PowerSHell-like option that addresses the main issue - 'rewstarting SNMP'.

Your original complaint is that your code does not stop all of the dependents.  Using force will always stop all dependents.  That is really the complete answer to your original question.

 

 

 

November 30th, 2011 5:15pm

I decided to try to understand why you see layers of dependencies.  I found that on WS2008 R2 HP managemnet does have a second layer.  It does not incluse anything but subservices from HP>  VSC is not  a dependency and, from my research, should not ever be a dependency.  Of course this does not stop someone from making it a dependency which could create issues.

Here is a recursive function that will display all dependencies of any service or all services,

The code returns the service names in order and can be used to restart all services in dependent order.

function Get-Depends{
    [CmdLetBinding()]
    Param(
		$servicename='SNMP',
		$level = 0,
		[switch]$infoonly
	)
		try{
		     Write-Verbose $($("`t" * $level)+$servicename)
		     $servicename
		     $services=get-service $servicename -ea stop | where{$_.dependentservices}|select -expand dependentservices
		     if($services){
		          $services | %{Get-Depends $($_.Name) ($level+1) }
		    }
	    }
	    catch{
	        $_
	    }
}
$depends=Get-Depends -v


The verbose switch displays a hierarchical display of names to ilustrate the dependencies.

Free Windows Admin Tool Kit Click here and download it now
November 30th, 2011 6:16pm

Hello 

iam very new to powershell, i made a one live to restart a service Workstation with its dependecies:

Restart-Service LanmanWorkstation -force; Get-Service Workstation -depend| Start-Service -name {$_.name}
Works well for me, I hope it make sense for you.

Best regards

August 23rd, 2013 2:43pm

Any final solution with full source code?
Free Windows Admin Tool Kit Click here and download it now
September 11th, 2013 5:59am

Any final solution with full so
May 29th, 2014 9:30pm

You are answering a question that is 9 months old and was really just spam.  Look at the link.
Free Windows Admin Tool Kit Click here and download it now
May 29th, 2014 9:34pm

There is dependencies with parent and child service. When I tried to use "Force" flag both child and parent are getting stopped. So I brewed small script to full fill my task

************ Stop Parent and Child Service ************

$SrvName = "mmcss"
$DepSrv = Get-Service $SrvName
$DepSrvLst = $DepSrv.DependentServices

Write-Host "Below given is the list of Dependent Services"
$DepSrvLst
$CntSrv = $DepSrvLst.Count
Write-Output "`nDependent Service Count is: $CntSrv"
Write-Output "`nStopping Parent and its Dependent Services"

Stop-Service $SrvName -Force
$DepSrv = Get-Service $SrvName
$DepSrvLst = $DepSrv.DependentServices
Write-Host "`nStatus of Services"
Write-Host "`nStatus   Name               DisplayName"
Write-Host "`---------------------------------------"
$DepSrv
$DepSrvLst

************ Start Parent and Child Service ************

$SrvName = "SQL Server (SQLEXPRESS)"
$DepSrv = Get-Service $SrvName
$DepSrvLst = $DepSrv.DependentServices

Write-Host "Starting the Prarent and Dependent Services"
$DepSrv.DependentServices | Start-Service
$DepSrv = Get-Service $SrvName
$DepSrvLst = $DepSrv.DependentServices
Write-Host "`nStatus of Services"
$DepSrv
$DepSrvLst

December 15th, 2014 7:20am

Hi Scott,

I know this is a reply after a long long time.  I had the same requirement and based on you code in the question managed to come up with a script. Hope someone will benefit putting the answer here.

This script works fine for me. Tested with few services and so far so good.

Param (
[Parameter(Mandatory=$true)] [String]$ServiceName
)

[System.Collections.ArrayList]$ServicesToRestart = @()

function Custom-GetDependServices ($ServiceInput)
{
	#Write-Host "Name of `$ServiceInput: $($ServiceInput.Name)"
	#Write-Host "Number of dependents: $($ServiceInput.DependentServices.Count)"
	If ($ServiceInput.DependentServices.Count -gt 0)
	{
		ForEach ($DepService in $ServiceInput.DependentServices)
		{
			#Write-Host "Dependent of $($ServiceInput.Name): $($Service.Name)"
			If ($DepService.Status -eq "Running")
			{
				#Write-Host "$($DepService.Name) is running."
				$CurrentService = Get-Service -Name $DepService.Name
				
                # get dependancies of running service
				Custom-GetDependServices $CurrentService                
			}
			Else
			{
				Write-Host "$($DepService.Name) is stopped. No Need to stop or start or check dependancies."
			}
			
		}
	}
    Write-Host "Service to Stop $($ServiceInput.Name)"
    if ($ServicesToRestart.Contains($ServiceInput.Name) -eq $false)
    {
        Write-Host "Adding service to stop $($ServiceInput.Name)"
        $ServicesToRestart.Add($ServiceInput.Name)
    }
}

# Get the main service
$Service = Get-Service -Name $ServiceName

# Get dependancies and stop order
Custom-GetDependServices -ServiceInput $Service


Write-Host "-------------------------------------------"
Write-Host "Stopping Services"
Write-Host "-------------------------------------------"
foreach($ServiceToStop in $ServicesToRestart)
{
    Write-Host "Stop Service $ServiceToStop"
    Stop-Service $ServiceToStop -Verbose #-Force
}
Write-Host "-------------------------------------------"
Write-Host "Starting Services"
Write-Host "-------------------------------------------"
# Reverse stop order to get start order
$ServicesToRestart.Reverse()

foreach($ServiceToRestart in $ServicesToRestart)
{
    Write-Host "Start Service $ServiceToRestart"
    Start-Service $ServiceToRestart -Verbose
}
Write-Host "-------------------------------------------"
Write-Host "Restart of services completed"
Write-Host "-------------------------------------------"

Cheers!

Chaminda

Free Windows Admin Tool Kit Click here and download it now
August 7th, 2015 3:21am

Good stuff!  Thanks for posting!
August 10th, 2015 3:48pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics